package com.szty.lib_pen.sendPoint

import android.app.Service
import android.content.Intent
import android.os.Binder
import android.os.IBinder
import android.util.Log
import androidx.room.Room
import com.blankj.utilcode.util.GsonUtils
import com.sjh.baseutils.loge
import com.sjh.lib_app.AppConfig
import com.szty.lib_pen.sendPoint.longConnect.client.HeartBeatHandler
import com.szty.lib_pen.sendPoint.longConnect.client.HeartBeatListener
import com.szty.lib_pen.sendPoint.longConnect.client.HeartBeatMessageFactory
import com.szty.lib_pen.sendPoint.longConnect.manager.ClientConnectManager
import com.szty.lib_pen.sendPoint.longConnect.manager.SessionManager
import com.szty.lib_pen.oidbluetooth.BluetoothLEService
import com.szty.lib_pen.sendPoint.room.AppDatabase
import com.szty.lib_pen.sendPoint.room.DotBean
import com.tqltech.tqlpencomm.bean.Dot
import org.apache.mina.core.service.IoService
import org.apache.mina.core.session.IoSession

/**
 *    author : SunJH
 *    date   : 2021/4/30 0030
 *    desc   : 发送笔迹点到服务器的服务
 */
class SendPointService : Service() {
    private var pointNumber = 0
    private val TAG = javaClass.simpleName
    private var nowSendPoint: DotBean? = null
    private var isConnectSock = false
    private var isSendPointing = false
    private var db: AppDatabase? = null
    private val sendStatusListeners = arrayListOf<SendStatusListener>()
    private val heartBeatListener = object : HeartBeatListener() {
        override fun serviceActivated(arg0: IoService?) {
            super.serviceActivated(arg0)
            isConnectSock = true
            isSendPointing = false
            sendStatusListeners.forEach {
                it.connectStatusCall(true)
            }
        }

        override fun sessionDestroyed(arg0: IoSession?) {
            super.sessionDestroyed(arg0)
            isConnectSock = false
            sendStatusListeners.forEach {
                it.connectStatusCall(false)
            }
        }
    }
    private val heartBeatHandler = object : HeartBeatHandler() {
        override fun messageReceived(session: IoSession?, message: Any?) {
            super.messageReceived(session, message)
            if(message == null)return
            val message = message.toString()
            if (nowSendPoint == null) return
            if (!isConnectSock) return
            Log.i(TAG,"回复是:${message}")
            if (nowSendPoint != null && message == "${nowSendPoint!!.penMac}${nowSendPoint!!.id}") {
                removeLastData()
                if (isHasNextPoint()) {
                    sendNextPoint()
                } else {
                    isSendPointing = false
                }
            }else{
                "判断未通过".loge()
            }
        }
    }
    fun getConnectStatus()=isConnectSock
    private fun showPointCount() {
        if(pointNumber <0)pointNumber = 0
        sendStatusListeners.forEach {
            it.sendPointQuestion(pointNumber)
        }
    }

    private fun isHasNextPoint() = db?.dotDao()?.getFirstData() != null
    //发送下一个数据点
    private fun sendNextPoint() {
        val dotBean = db?.dotDao()?.getFirstData() ?: return
        sendPointToService(dotBean)
    }

    fun addSendStatusListener(sendStatusListener: SendStatusListener) {
        sendStatusListeners.add(sendStatusListener)
        sendStatusListener.connectStatusCall(isConnectSock)
        val all = db?.dotDao()?.getAll()
        sendStatusListener.sendPointQuestion(all?.size ?: 0)
    }

    fun removeSendStatusListener(sendStatusListener: SendStatusListener) {
        sendStatusListeners.remove(sendStatusListener)
    }

    /**
     * 删除数据点
     */
    private fun removeLastData() {
        val lastData = db?.dotDao()?.getFirstData() ?: return
        db?.dotDao()?.delete(lastData)
        pointNumber--

    }
    public fun deleteAllData(){
        pointNumber = 0
        db?.dotDao()?.deleteAll()
        showPointCount()
    }

    private val heartBeatMessageFactory = object : HeartBeatMessageFactory() {
        override fun getRequest(ioSession: IoSession?): Any {
            return super.getRequest(ioSession)
        }
    }

    inner class SendBind : Binder() {

        fun getService(): SendPointService {
            return this@SendPointService
        }
    }

    private fun sendPointToService(dot: DotBean) {
        nowSendPoint = dot
        Log.i(TAG,"发送是:${nowSendPoint!!.penMac}")
        nowSendPoint?.id = nowSendPoint?.uid?:0
        val json = GsonUtils.getGson().toJson(dot)
        SessionManager.getInstance().writeToServer(json)
    }

    fun savePointToLocation(dot: Dot, studentId: Int) {
        val nowPointMac = MacSettingHelper.instance.getNowPointMac(dot.timelong)
        if(nowPointMac.isNullOrEmpty())return
        val dotBean = DotBean(
            dot.BookID,
            dot.OwnerID,
            dot.PageID,
            dot.SectionID,
            dot.Counter,
            dot.force,
            dot.fx,
            dot.fy,
            dot.angle,
            nowPointMac.replace(":", "").toUpperCase(),
            0,
            dot.timelong,
            dot.typeStr,
            dot.x,
            dot.y,
            studentId
        )
        pointNumber++
        db?.dotDao()?.insertAll(dotBean)
        if (!isSendPointing&&isConnectSock) {
            isSendPointing = true
            sendNextPoint()
        }
    }

    override fun onBind(intent: Intent?): IBinder {
        return SendBind()
    }

    override fun onStart(intent: Intent?, startId: Int) {
        super.onStart(intent, startId)
        if (isConnectSock) return
        ClientConnectManager.getInstance().connect()
    }

    override fun onDestroy() {
        super.onDestroy()
        disConnect()
        db?.close()
    }

    private fun disConnect() {
        ClientConnectManager.getInstance().disConnect()
        SessionManager.getInstance().closeSession()
        SessionManager.getInstance().removeSession()
    }

    fun connectToService(){
        ClientConnectManager.getInstance().connect()
    }

    override fun onCreate() {
        super.onCreate()
        ClientConnectManager.getInstance()
            .init(heartBeatHandler, heartBeatListener, heartBeatMessageFactory)
        ClientConnectManager.getInstance().connect()
        db =
            Room.databaseBuilder(
                applicationContext,
                AppDatabase::class.java,
                AppConfig.getPointSQLTabName()
            )//数据库升级操作没有做，暂时直接新建表名
                .fallbackToDestructiveMigration()               //在数据库升级失败的情况下，重新创建数据库，但是会丢失之前的数据
                .allowMainThreadQueries()                       //强制可以在主线程运行
                .build()
        pointNumber = db?.dotDao()?.getCount()?:0

    }

}
